package cn.icanci.loopstack.ddk.admin.biz.service.impl;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import cn.icanci.loopstack.ddk.admin.biz.event.dict.DictEvent;
import cn.icanci.loopstack.ddk.admin.biz.event.resource.ResourceEvent;
import cn.icanci.loopstack.ddk.admin.biz.mapping.config.RegisterMapping;
import cn.icanci.loopstack.ddk.admin.biz.model.RegisterModel;
import cn.icanci.loopstack.ddk.admin.biz.service.*;
import cn.icanci.loopstack.ddk.admin.biz.utils.EnvUtils;
import cn.icanci.loopstack.ddk.admin.biz.utils.IDHolder;
import cn.icanci.loopstack.ddk.admin.dal.mapper.entity.RegisterDO;
import cn.icanci.loopstack.ddk.admin.dal.mapper.mapper.RegisterMapper;
import cn.icanci.loopstack.ddk.common.enums.BooleanEnum;
import cn.icanci.loopstack.ddk.common.model.PageList;
import cn.icanci.loopstack.ddk.common.model.config.*;
import cn.icanci.loopstack.ddk.common.socket.load.DictValueObjectDTO;
import cn.icanci.loopstack.ddk.common.socket.load.ResourceLoadResponseDTO;
import cn.icanci.loopstack.ddk.common.socket.load.ResourceValueObjectDTO;
import cn.icanci.loopstack.ddk.common.socket.publish.RegisterDTO;
import cn.icanci.loopstack.ddk.common.utils.PaginatorUtils;
import cn.icanci.loopstack.lsi.event.EventDispatcher;

/**
 * @author icanci
 * @since 1.0 Created in 2023/01/06 21:07
 */
@Service
public class RegisterServiceImpl implements RegisterService {
    @Resource
    private RegisterMapping     registerMapping;
    @Resource
    private RegisterMapper      registerMapper;
    @Resource
    private EventDispatcher     eventDispatcher;
    @Resource
    private AppService          appService;
    @Resource
    private GroupService        groupService;
    @Resource
    private TeamService         teamService;
    @Resource
    private NoticeConfigService noticeConfigService;
    @Resource
    private AppConfigService    appConfigService;

    @Override
    public PageList<RegisterModel> queryPage(String appId, int currentPage, int pageSize) {
        RegisterDO register = new RegisterDO();
        register.setEnv(EnvUtils.getEnv());
        register.setAppId(appId);

        currentPage = Math.max(currentPage - 1, 0);

        List<RegisterDO> ret = registerMapper.selectPage(register, currentPage, pageSize);

        PageList<RegisterVO> pageList = PaginatorUtils.formatPaginator(registerMapping.dos2vos(ret), currentPage, pageSize, registerMapper.total(register));
        if (CollectionUtils.isEmpty(pageList.getData())) {
            return new PageList<>(Lists.newArrayList(), pageList.getPaginator());
        }

        return new PageList(mapper(pageList.getData()), pageList.getPaginator());
    }

    private List<RegisterModel> mapper(Collection<RegisterVO> data) {
        List<RegisterModel> registerModels = Lists.newArrayList();
        for (RegisterVO register : data) {
            registerModels.add(mapper(register));
        }
        return registerModels;
    }

    private RegisterModel mapper(RegisterVO register) {
        AppVO appVO = appService.queryByAppId(register.getAppId());
        TeamVO teamVO = teamService.queryByTeamUuid(appVO.getTeamUuid());
        GroupVO groupVO = groupService.queryByGroupUuid(teamVO.getGroupUuid());
        RegisterModel model = new RegisterModel();
        model.setGroupName(groupVO.getGroupName());
        model.setTeamName(teamVO.getTeamName());
        model.setAppName(appVO.getAppName());
        model.setAppId(register.getAppId());
        model.setClientAddress(register.getClientAddress());
        model.setClientPort(register.getClientPort());
        model.setRegisterTime(register.getRegisterTime());
        model.setLastUpdateTime(register.getLastUpdateTime());
        model.setIsDelete(register.getIsDelete());
        return model;
    }

    @Override
    public void publishDict(String uuid) {
        eventDispatcher.fire(new DictEvent(uuid), true);
    }

    @Override
    public void publishResource(String resource, String value) {
        eventDispatcher.fire(new ResourceEvent(resource, value), true);
    }

    @Override
    public boolean doRegister(RegisterDTO register) {
        if (register == null || StringUtils.isBlank(register.getAppId()) || StringUtils.isBlank(register.getClientAddress()) || register.getClientPort() <= 0) {
            return false;
        }

        String appId = register.getAppId();
        AppVO app = appService.queryByAppId(appId);
        if (app == null) {
            return false;
        }
        RegisterDO registerDO = new RegisterDO();
        registerDO.setEnv(EnvUtils.getEnv());
        registerDO.setAppId(register.getAppId());
        registerDO.setClientAddress(register.getClientAddress());
        registerDO.setClientPort(register.getClientPort());
        RegisterDO old = registerMapper.selectOne(registerDO);
        if (old == null) {
            return registerMapper.insert(buildRequest(register)) > 1;
        }

        old.setUpdateTime(new Date());
        old.setLastUpdateTime(new Date());
        return registerMapper.update(old) > 1;
    }

    @Override
    public ResourceLoadResponseDTO loadByAppId(String appId) {
        ResourceLoadResponseDTO response = new ResourceLoadResponseDTO();

        AppVO appVO = appService.queryByAppId(appId);
        if (appVO != null) {
            String uuid = appVO.getUuid();
            List<AppConfigVO> appConfigList = appConfigService.queryByAppUuid(uuid, BooleanEnum.NO.getCode());
            if (CollectionUtils.isNotEmpty(appConfigList)) {
                Set<DictValueObjectDTO> dictValues = Sets.newHashSet();
                for (AppConfigVO appConfigVO : appConfigList) {
                    dictValues.add(new DictValueObjectDTO(appConfigVO.getAppConfigName(), appConfigVO.getAppConfigValue()));
                }
                response.setDictValues(dictValues);
            }

            List<NoticeConfigVO> noticeConfigList = noticeConfigService.queryByAppUuid(uuid, BooleanEnum.NO.getCode());
            if (CollectionUtils.isNotEmpty(noticeConfigList)) {
                Set<ResourceValueObjectDTO> resourceValues = Sets.newHashSet();
                for (NoticeConfigVO noticeConfigVO : noticeConfigList) {
                    resourceValues.add(new ResourceValueObjectDTO(noticeConfigVO.getNoticeConfigResource(), noticeConfigVO.getNoticeValue()));
                }
                response.setResourceValues(resourceValues);
            }
        }

        return response;
    }

    @Override
    public List<RegisterVO> queryAll() {
        return registerMapping.dos2vos(registerMapper.selectAll(EnvUtils.getEnv()));
    }

    @Override
    public void update(RegisterVO register) {
        registerMapper.update(registerMapping.vo2do(register));
    }

    @Override
    public List<RegisterVO> queryByAppId(String appId) {
        return registerMapping.dos2vos(registerMapper.queryByAppId(appId, EnvUtils.getEnv()));
    }

    private RegisterDO buildRequest(RegisterDTO register) {
        RegisterDO registerDO = new RegisterDO();
        registerDO.setUuid(IDHolder.generateNoBySnowFlake("REG"));
        registerDO.setDesc(register.getClientAddress());
        registerDO.setCreateTime(new Date());
        registerDO.setUpdateTime(new Date());
        registerDO.setIsDelete(0);
        registerDO.setEnv(EnvUtils.getEnv());
        registerDO.setClientAddress(register.getClientAddress());
        registerDO.setClientPort(register.getClientPort());
        registerDO.setAppId(register.getAppId());
        registerDO.setRegisterTime(new Date());
        registerDO.setLastUpdateTime(new Date());
        return registerDO;
    }
}
